
import javax.swing.*;
import java.applet.*;
import java.awt.*;
import java.awt.event.*;

public class e2PieceBagPane extends JPanel implements MouseListener,MouseMotionListener {

    private static final long serialVersionUID = 42L;
    e2Applet topapplet;
    // Variables for double buffering
    Image myimage;
    Graphics buffer;
    static final int WIDTH = 1600;
    static final int HEIGHT = 1600;
    int panewidth;
    int paneheight;
    int piecewidth;
    int pieceheight;
    int boardstartx;
    int boardstarty;
    int rownb;
    int colnb;
    int piecebyrow;
    int i, j;
	int mouseX, mouseY;
	int prevmouseX, prevmouseY;
    Image hiddenimage;
    Graphics hiddengraphics;
	boolean incrementalpaint;
	e2piece [] [] piecetab;

    public e2PieceBagPane(e2Applet in_applet) {
        topapplet = in_applet;
        piecewidth = topapplet.param.piece_w;
        pieceheight = topapplet.param.piece_h;
        colnb = 4;
        rownb = (int) (((topapplet.param.rownb * topapplet.param.colnb) / colnb) + 1);
        panewidth = colnb * piecewidth;
        paneheight = (rownb + 1) * pieceheight;
        boardstartx = 0;
        boardstarty = 0;
        piecetab = new e2piece[colnb][rownb];
        e2piece temppiece;
        e2piecelist unplacedlist = topapplet.game.get_unplaced_pieces();
        unplacedlist.restart();
		for (i=0;i<rownb;i++) {
			for (j=0;j<colnb;j++) {
            	if (unplacedlist.hasNext()) {
                	temppiece = unplacedlist.next();
                    temppiece.set_position(i,j);
                    piecetab[j][i] = temppiece;
                } else {
                	piecetab[j][i] = null;
                }
 			}
		}
		incrementalpaint = false;
        // double buffering initialisation
        myimage = topapplet.createImage(panewidth, paneheight);
        buffer = myimage.getGraphics();
        hiddenimage = topapplet.createImage(piecewidth, pieceheight);
        hiddengraphics = hiddenimage.getGraphics();
        
        
        setPreferredSize(new Dimension(panewidth, paneheight));
        addMouseListener(this);
		addMouseMotionListener(this);

    }
    
	public void update_piece_tab() {
		
        e2piece temppiece;
        e2position tempposition;
        e2piecelist unplacedlist = topapplet.game.get_unplaced_pieces();
        e2piecelist waiting_pieces;
        waiting_pieces = new e2piecelist();
        //waiting_pieces.restart();
        unplacedlist.restart();
        if (topapplet.param.piecebag_lockpositions == false) {
        	for (i=0;i<rownb;i++) {
        		for (j=0;j<colnb;j++) {
        			if (topapplet.param.selection == true) {
        				if (unplacedlist.hasNext()) {
            				temppiece = unplacedlist.next();
                            while ((temppiece != null) && (temppiece.isHighlighted() == false)) {
            					waiting_pieces.add_piece(temppiece);
                                //waiting_pieces.restart();
        						//System.out.println(" pushing out piece at "+j+" "+i);
                                temppiece = null;
                                if (unplacedlist.hasNext()) {
                        				temppiece = unplacedlist.next();
                                } else {
                                	temppiece = null;
                                	break;
                                }
                            }
            				if (temppiece != null) {
                				temppiece.set_position(i,j);
                				piecetab[j][i] = temppiece;
        						//System.out.println(" placing highlighted piece at "+j+" "+i);
            				} else if (waiting_pieces.hasNext()) {
            					temppiece = waiting_pieces.next();
            					temppiece.set_position(i,j);
            					piecetab[j][i] = temppiece;
        						//System.out.println(" placing first waiting piece at "+j+" "+i);
            				} else {
            					piecetab[j][i] = null;
        						//System.out.println(" first no more piece at "+j+" "+i);
                            }
        				} else if (waiting_pieces.hasNext()) {
            				temppiece = waiting_pieces.next();
            				temppiece.set_position(i,j);
            				piecetab[j][i] = temppiece;
        					//System.out.println(" placing waiting piece at "+j+" "+i);
       					
            			} else {
            				piecetab[j][i] = null;
        					//System.out.println(" no more piece at "+j+" "+i);
            			}
        				
        			} else if (unplacedlist.hasNext()) {
        				temppiece = unplacedlist.next();
        				temppiece.set_position(i,j);
        				piecetab[j][i] = temppiece;
        			} else {
        				piecetab[j][i] = null;
        			}
        		}
        	}
        } else {
        	for (i=0;i<rownb;i++) {
        		for (j=0;j<colnb;j++) {
        				piecetab[j][i] = null;
         		}
        	}
        	while (unplacedlist.hasNext()) {
				temppiece = unplacedlist.next();
				piecetab[temppiece.position.col][temppiece.position.row] = temppiece;
            }
        }
		incrementalpaint = false;		
	}
	
	public e2piece get_piece_at(int in_col, int in_row) {
			return piecetab[in_col][in_row];
	}
	
	public void paintFullPane(Graphics g) {
        e2piecelist unplacedlist;
        e2piece temppiece;
        
		update_piece_tab();
        
        unplacedlist = topapplet.game.get_unplaced_pieces();
        unplacedlist.restart();
        prevmouseX = mouseX;
        prevmouseY = mouseY;
		
		buffer.setColor(Color.black);
		buffer.fillRect(0,0,2*boardstartx + colnb*piecewidth,2*boardstarty + rownb*pieceheight);				
		while(unplacedlist.hasNext()) {
        	temppiece = unplacedlist.next();
        	j = temppiece.position.col;
        	i = temppiece.position.row;
            if ((topapplet.param.drag == true) && (temppiece.id == topapplet.param.dragged_piece.id)) {
            	//do not draw the dragged piece at its position
            } else {
            	buffer.drawImage(topapplet.param.pieceimage[temppiece.id][temppiece.position.rotation][temppiece.hilite],topapplet.param.board_x + j*topapplet.param.piece_w,topapplet.param.board_y + i*topapplet.param.piece_h, this);
            }
			buffer.setColor(Color.white);
			buffer.drawRect(topapplet.param.board_x + j*topapplet.param.piece_w,topapplet.param.board_y + i*topapplet.param.piece_h, topapplet.param.board_x + j*topapplet.param.piece_w + topapplet.param.piece_w,topapplet.param.board_y + i*topapplet.param.piece_h + topapplet.param.piece_h);				
		}
		for (i=0;i<rownb;i++) {
			for (j=0;j<colnb;j++) {
				buffer.setColor(Color.white);
				buffer.drawRect(topapplet.param.board_x + j*topapplet.param.piece_w,topapplet.param.board_y + i*topapplet.param.piece_h, topapplet.param.board_x + j*topapplet.param.piece_w + topapplet.param.piece_w,topapplet.param.board_y + i*topapplet.param.piece_h + topapplet.param.piece_h);				
				
			}
		}
        //copy the rectangle under the mouse
        hiddengraphics.drawImage(myimage,0,0,piecewidth,pieceheight,mouseX-piecewidth/2, mouseY-pieceheight/2,mouseX + piecewidth/2, mouseY + pieceheight/2,this);
        if (topapplet.param.drag == true) {
        	buffer.drawImage(topapplet.param.pieceimage[topapplet.param.dragged_piece.id][topapplet.param.dragged_piece.position.rotation][topapplet.param.dragged_piece.hilite],mouseX - (int) topapplet.param.piece_w/2,mouseY - (int) topapplet.param.piece_h/2, this);
        	buffer.setColor(Color.white);
			buffer.drawRect(mouseX - (int) topapplet.param.piece_w/2, mouseY - (int) topapplet.param.piece_h/2, topapplet.param.piece_w - 1, topapplet.param.piece_h - 1);				
        }
		g.drawImage(myimage , 0 , 0 , this);
		
	}
	
	public void paintIncrementalPane(Graphics g) {
        e2piece temppiece;
        
		int i,j;
		int mousei,mousej;
		int prevmousei,prevmousej;
        mousej = (int) ((mouseX - boardstartx)/piecewidth);
        mousei = (int) ((mouseY - boardstarty)/pieceheight);
        prevmousej = (int) ((prevmouseX - boardstartx)/piecewidth);
        prevmousei = (int) ((prevmouseY - boardstarty)/pieceheight);

        //update around previous mouse position
        //draw the rectangle under the previous mouse position 
        buffer.drawImage(hiddenimage, prevmouseX - piecewidth/2, prevmouseY - pieceheight/2,this); 
        prevmouseX = mouseX;
        prevmouseY = mouseY;
        //update around new mouse position
        //copy the rectangle under the new mouse position
        hiddengraphics.drawImage(myimage,0,0,piecewidth,pieceheight,mouseX-piecewidth/2, mouseY-pieceheight/2,mouseX + piecewidth/2, mouseY + pieceheight/2,this);
        if (topapplet.param.drag == true) {
        	buffer.drawImage(topapplet.param.pieceimage[topapplet.param.dragged_piece.id][topapplet.param.dragged_piece.position.rotation][topapplet.param.dragged_piece.hilite],mouseX - (int) topapplet.param.piece_w/2,mouseY - (int) topapplet.param.piece_h/2, this);
        	buffer.setColor(Color.white);
			buffer.drawRect(mouseX - (int) topapplet.param.piece_w/2, mouseY - (int) topapplet.param.piece_h/2, topapplet.param.piece_w - 1, topapplet.param.piece_h - 1);				
        }
		g.drawImage(myimage , 0 , 0 , this);
		
	}

	public void paintComponent(Graphics g) {
		super.paintComponent(g);
		if ((incrementalpaint == false) || (topapplet.param.redraw_piecebag == true) ) {
			paintFullPane(g);
			incrementalpaint = true;
            topapplet.param.redraw_piecebag = false;
		} else {
			paintIncrementalPane(g);
		}
	}
	
	public void mousePressed(MouseEvent evt) {
		int x,y;
		int i,j;
		e2piece temppiece;
		x = evt.getX(); 
		y = evt.getY();
        j = (int) ((x - boardstartx)/piecewidth);
        i = (int) ((y - boardstarty)/pieceheight);
		if( evt.getModifiers() == InputEvent.BUTTON3_MASK ) {
        	//System.out.println(" right mouse pressed at "+j+" "+i);
        	if (topapplet.param.drag == false) {
        		temppiece = get_piece_at(j,i);
        		if (temppiece != null) {
                	temppiece.rotate(1);
        		}
        	} else {
        			topapplet.param.dragged_piece.rotate(1);
        	}
        } else {
        	//System.out.println(" left mouse pressed at "+j+" "+i);
        	if (topapplet.param.drag == false) {
        		temppiece = get_piece_at(j,i);
        		if (temppiece != null) {
        			topapplet.param.drag = true;
        			topapplet.param.dragged_piece = temppiece;
        		}
        	} else {
        		temppiece = get_piece_at(j,i);
        		if ((temppiece == null) || ( (temppiece.position.col == j) && (temppiece.position.row == i)) ) {
        			topapplet.param.dragged_piece.set_position(i,j);
         			topapplet.param.drag = false;
        			topapplet.param.dragged_piece = null;
        		}
        	
        	}
        }
        update_piece_tab();
        repaint();
	}
    
	public void mouseReleased(MouseEvent evt) {
		int x,y;
		int i,j;
		x = evt.getX(); 
		y = evt.getY();
        j = (int) ((x - boardstartx)/piecewidth);
        i = (int) ((y - boardstarty)/pieceheight);
        //System.out.println(" mouse released at "+j+" "+i);
        update_piece_tab();
        repaint();
	}
	public void mouseEntered(MouseEvent evt) {
        update_piece_tab();
        repaint();
	}
	public void mouseExited(MouseEvent evt) {
		mouseX = -piecewidth - 1;
		mouseY = -pieceheight - 1;
        update_piece_tab();
        repaint();
	}
	public void mouseClicked(MouseEvent evt) {
		int i,j;
		int x,y;
		x = evt.getX(); 
		y = evt.getY();
        update_piece_tab();
        repaint();
	}
	public void mouseDragged(MouseEvent evt) {
		int x,y;
		int i,j;
		x = evt.getX(); 
		y = evt.getY();
        j = (int) ((x - boardstartx)/piecewidth);
        i = (int) ((y - boardstarty)/pieceheight);
        //System.out.println(" mouse dragged at "+j+" "+i);
        repaint();
	}
	public void mouseMoved(MouseEvent evt) {
		int x,y;
		mouseX = evt.getX(); 
		mouseY = evt.getY();
        repaint();
	}
}
